/**
 * 
 */
package com.cqan.controller;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.servlet.http.HttpServletRequest;

import org.apache.log4j.Logger;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.servlet.mvc.multiaction.MultiActionController;

import com.cqan.account.entity.User;
import com.cqan.entity.pk.IdEntity;
import com.cqan.exception.AppException;
import com.cqan.orm.Page;

/**
 * @Description Controller 基本类
 * @author slaton.wu@gmail.com
 * @date 2012-6-29下午7:30:39
 * 
 */
public class BaseController<Entity extends IdEntity> extends
		MultiActionController {

	protected static final Logger logger = Logger.getLogger("ds.debug");

	protected Class<Entity> entityClass;

	protected Page<Entity> page = new Page<Entity>(15);

	protected User getUserDetails() {
		Object obj = SecurityContextHolder.getContext().getAuthentication()
				.getPrincipal();
		if (obj instanceof User) {
			return (User) obj;
		}
		return null;
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	protected Entity getRequestEntity(HttpServletRequest req)
			throws AppException {
		try {
			this.entityClass = ((Class) ((ParameterizedType) getClass()
					.getGenericSuperclass()).getActualTypeArguments()[0]);
			if (entityClass != null) {
				Entity entity = entityClass.newInstance();
				Field[] fields = entityClass.getDeclaredFields();
				for (Field field : fields) {
					String value = req.getParameter(field.getName());
					if (value != null && !"".equals(value)) {
						setFieldValue(entity, field.getName(), value);
					}
				}
				return entity;
			}
		} catch (Exception e) {
			logger.debug(e.getLocalizedMessage());
			throw new AppException("base.assignment");
		}
		return null;
	}

	/**
	 * SET 值
	 * @param bean 对象
	 * @param propertyName 属性名称
	 * @param propertyValue 属性值
	 */
	private void setFieldValue(Object bean, String propertyName,
			String propertyValue) {
		Class<?> cls = bean.getClass();
		// 取出bean里的所有方法
		Method[] methods = cls.getDeclaredMethods();
		try {
			Field field = bean.getClass().getDeclaredField(propertyName);
			String fieldSetName = parSetName(field.getName());
			if (!checkSetMet(methods, fieldSetName)) {
			return;
			}
			Method fieldSetMet = cls.getMethod(fieldSetName, field.getType());
			if (null != propertyName && !"".equals(propertyName)) {
				String fieldType = field.getType().getSimpleName();
				if ("String".equals(fieldType)) {
					fieldSetMet.invoke(bean, propertyValue);
				} else if ("Date".equals(fieldType)) {
					Date temp = parseDate(propertyValue);
					fieldSetMet.invoke(bean, temp);
				} else if ("Integer".equals(fieldType)
						|| "int".equals(fieldType)) {
					Integer intval = Integer.parseInt(propertyValue);
					fieldSetMet.invoke(bean, intval);
				} else if ("Long".equalsIgnoreCase(fieldType)) {
					Long temp = Long.parseLong(propertyValue);
					fieldSetMet.invoke(bean, temp);
				} else if ("Double".equalsIgnoreCase(fieldType)) {
					Double temp = Double.parseDouble(propertyValue);
					fieldSetMet.invoke(bean, temp);
				} else if ("Boolean".equalsIgnoreCase(fieldType)) {
					propertyValue = propertyValue.equals("0")?"false":propertyValue.equals("1")?"true":null;
					Boolean temp = Boolean.parseBoolean(propertyValue);
					fieldSetMet.invoke(bean, temp);
				} else {
					logger.debug("not supper type " + fieldType);
				}
			}
		} catch (Exception e) {
		}

	}

	/**
	 * 格式化string为Date
	 * 
	 * @param datestr
	 * @return date
	 */
	private Date parseDate(String datestr) {
		if (null == datestr || "".equals(datestr)) {
			return null;
		}
		try {
			String fmtstr = null;
			if (datestr.indexOf(':') > 0) {
				fmtstr = "yyyy-MM-dd HH:mm:ss";
			} else {

				fmtstr = "yyyy-MM-dd";
			}
			SimpleDateFormat sdf = new SimpleDateFormat(fmtstr);
			return sdf.parse(datestr);
		} catch (Exception e) {
			return null;
		}
	}

	/**
	 * 判断是否存在某属性的 set方法
	 * 
	 * @param methods
	 * @param fieldSetMet
	 * @return boolean
	 */
	private boolean checkSetMet(Method[] methods, String fieldSetMet) {
		for (Method met : methods) {
			if (fieldSetMet.equals(met.getName())) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 拼接在某属性的 set方法
	 * 
	 * @param fieldName
	 * @return String
	 */
	private String parSetName(String fieldName) {
		if (null == fieldName || "".equals(fieldName)) {
			return null;
		}
		return "set" + fieldName.substring(0, 1).toUpperCase()
				+ fieldName.substring(1);
	}
	
	/**
	 * 复制orig对象中属性非空值到dest中。
	 * @param dest
	 * @param orig
	 * @throws IllegalAccessException 
	 * @throws Exception 
	 */
	protected void copyProperties(Object dest, Object orig) throws Exception {
		if (orig==null||dest==null) {
			return;
		}
		Field[] origs = orig.getClass().getDeclaredFields();
		Field[] fields = dest.getClass().getDeclaredFields();
		for (Field field : fields) {
			for (Field f : origs) {
				if (f.getName().equals(field.getName())) {
					f.setAccessible(true);
					Object value = f.get(orig);
					if (value!=null) {
						Method fieldSetMet = dest.getClass().getMethod(parSetName(f.getName()), field.getType());
						fieldSetMet.invoke(dest, value);
					}
				}
			}
			
		}
		
	}

}
